package com.redoor.app.stake.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 时间计算工具
 *
 * Created by leoliu on 2017/3/10.
 */
@Component
public class TimeCalculationUtil {

    private static final Logger logger = LoggerFactory.getLogger(TimeCalculationUtil.class) ;

    private Map<String, String> weeks = new HashMap<>() ;

    public TimeCalculationUtil(){
        this.weeks.put("Mon", "周一") ;
        this.weeks.put("Tue", "周二") ;
        this.weeks.put("Wed", "周三") ;
        this.weeks.put("Thu", "周四") ;
        this.weeks.put("Fri", "周五") ;
        this.weeks.put("Sat", "周六") ;
        this.weeks.put("Sun", "周日") ;
    }


    public boolean isTimeOutOfRange(Date date){
        if(date == null){
            return false ;
        }
        Calendar c = Calendar.getInstance() ;
        c.set(2038, 1, 19) ;
        long d = c.getTime().getTime() ;
        long s = date.getTime() ;
        return s > d ;
    }

    /**
     * 计算 source 到 target 之间相差几个月
     *
     * @param target
     * @param source
     * @return
     */
    public int getDiffrentMonth(String target, String source) {
        String[] targetSplit = target.split("-") ;
        String[] sourceSplit = source.split("-") ;
        if(targetSplit.length != 3 || sourceSplit.length != 3){
            return 0 ;
        }
        int tyear = Integer.parseInt(targetSplit[0]) ;
        int syear = Integer.parseInt(sourceSplit[0]) ;
        int tmonth = Integer.parseInt(targetSplit[1]) ;
        int smonth = Integer.parseInt(sourceSplit[1]) ;
        int tDay = Integer.parseInt(targetSplit[2]) ;
        int sDay = Integer.parseInt(sourceSplit[2]) ;

        Calendar scalendar = Calendar.getInstance() ;
        scalendar.set(syear, smonth, sDay) ;
        Calendar tcalendar = Calendar.getInstance() ;
        tcalendar.set(tyear, tmonth, tDay) ;

        Calendar c = Calendar.getInstance() ;
        c.setTimeInMillis(tcalendar.getTimeInMillis() - scalendar.getTimeInMillis()) ;
        int year = c.get(Calendar.YEAR) ;
        logger.debug("get year=" + year); ;
        int month = c.get(Calendar.MONTH) ;
        int day = c.get(Calendar.DAY_OF_YEAR) ;
        if(day > 0){
            month += 1 ;
        }

        return (year - 1970) * 12 + month ;
    }

    /**
     * 把日期转化为星期
     *
     * @param date
     * @return
     */
    public String dateToWeek(String date) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd") ;
        Date d = formatter.parse(date) ;
        return this.dateToWeek(d) ;
    }

    public String dateToWeek(Date d){
        SimpleDateFormat weekFormatter = new SimpleDateFormat("E") ;
        String week = weekFormatter.format(d) ;
        if(weeks.containsKey(week)){
            return weeks.get(week) ;
        }
        return week ;
    }

    /**
     * 计算 source 加 step 天 的日期
     *
     * @param source
     * @param step
     * @param formatter
     * @return
     * @throws ParseException
     */
    public String dateAdd(String source, int step, SimpleDateFormat formatter) throws ParseException {
        if(formatter == null){
            formatter = new SimpleDateFormat("yyyy-MM-dd") ;
        }
        Date sdate = formatter.parse(source) ;
        Calendar c = Calendar.getInstance() ;
        c.setTime(sdate) ;
        c.add(Calendar.DAY_OF_MONTH, step) ;
        return formatter.format(c.getTime()) ;
    }

    /**
     * 计算两个日期之间相差多少天（包含最后一天）
     *
     * @param source - 开始日期，会被格式化为 yyyy-MM-dd 格式
     * @param target - 结束日期，会被格式化为 yyyy-MM-dd 格式
     * @return
     * @throws ParseException
     */
    public int getDifferenceDays(String source, String target) throws ParseException {
        return this.getDifferenceDays(source, target, true) ;
    }

    /**
     * 计算两个日期之间相差多少天
     *
     * @param source - 开始日期，会被格式化为 yyyy-MM-dd 格式
     * @param target - 结束日期，会被格式化为 yyyy-MM-dd 格式
     * @param containTheLast - 是否包含最后一天，true - 包含，false - 不包含
     * @return
     * @throws ParseException
     */
    public int getDifferenceDays(String source, String target, boolean containTheLast) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd") ;
        Date sdate = formatter.parse(source) ;
        Date tdate = formatter.parse(target) ;
        return getDifferenceDays(sdate,tdate,containTheLast);
    }

    /**
     * 计算两个日期之间相差多少天
     *
     * @param source - 开始日期，会被格式化为 yyyy-MM-dd 格式
     * @param target - 结束日期
     * @return
     * @throws ParseException
     */
    public int getDifferenceDays(String source, Date target) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd") ;
        Date sdate = formatter.parse(source) ;
        return getDifferenceDays(sdate,target,true);
    }

    /**
     * 计算两个日期之间相差多少天
     *
     * @param source - 开始日期
     * @param target - 结束日期
     * @param containTheLast - 是否包含最后一天，true - 包含，false - 不包含
     * @return
     * @throws ParseException
     */
    public int getDifferenceDays(Date source, Date target, boolean containTheLast){
        long milliseconds = target.getTime() - source.getTime() ;
        long seconds = milliseconds / 1000 ;
        return (int)(seconds / (60 * 60 * 24)) + (containTheLast ? 1 : 0) ;
    }

    /**
     * 获取上一个月
     *
     * @param year
     * @param month
     * @param formartter
     * @return
     */
    public String getPreMonth(int year, int month, SimpleDateFormat formartter){
        if(month < 1 || month > 12){
            return "" ;
        }
        GregorianCalendar calendar = new GregorianCalendar() ;
        calendar.set(GregorianCalendar.YEAR, year) ;
        calendar.set(GregorianCalendar.MONTH, month) ;
        calendar.add(GregorianCalendar.MONTH, -2) ;
        if(formartter == null){
            formartter = new SimpleDateFormat("yyyy-MM") ;
        }
        return formartter.format(calendar.getTime()) ;
    }

    /**
     * 计算一个月有多少天
     *
     * @param year
     * @param month
     * @return
     */
    public int getTotalDaysOfMonth(int year, int month){
        if(month < 1 || month > 12){
            return 0 ;
        }

        Calendar calendar = Calendar.getInstance() ;
        calendar.set(Calendar.YEAR, year) ;
        calendar.set(Calendar.MONTH, month - 1 ) ;
        int days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) ;

        return days ;
    }

}
